Micron Document
baubs git

Node / mirrors / respira / commits / 65275c0

Commit 65275c0557ecc4e040d1736485880121fe097f2c


Parents : 89bc55b
Author : Jan-Henrik Bruhn <jan-henrik.bruhn@offis.de>
Date : 2025-12-27T16:56:26+01:00

fix: Add memoization to PatternCanvas expensive computations

Extract inline calculations to useMemo hooks to prevent unnecessary
recalculations on every render. Memoized displayPattern selection
and pattern dimensions calculation improve performance with large patterns.

Fixes #34

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Changes

1 files changed, 52 insertions(+), 56 deletions(-)


Diff

diff --git a/src/components/PatternCanvas/PatternCanvas.tsx b/src/components/PatternCanvas/PatternCanvas.tsx
index f791876..fae8a58 100644
--- a/src/components/PatternCanvas/PatternCanvas.tsx
+++ b/src/components/PatternCanvas/PatternCanvas.tsx
@@ -1,4 +1,4 @@
-import { useRef } from "react";
+import { useRef, useMemo } from "react";
import { useShallow } from "zustand/react/shallow";
import {
useMachineStore,
@@ -109,6 +109,26 @@ export function PatternCanvas() {
? "text-tertiary-600 dark:text-tertiary-400"
: "text-gray-600 dark:text-gray-400";
+ // Memoize the display pattern to avoid recalculation
+ const displayPattern = useMemo(
+ () => uploadedPesData || pesData,
+ [uploadedPesData, pesData],
+ );
+
+ // Memoize pattern dimensions calculation
+ const patternDimensions = useMemo(() => {
+ if (!displayPattern) return null;
+ const width = (
+ (displayPattern.bounds.maxX - displayPattern.bounds.minX) /
+ 10
+ ).toFixed(1);
+ const height = (
+ (displayPattern.bounds.maxY - displayPattern.bounds.minY) /
+ 10
+ ).toFixed(1);
+ return `${width} × ${height} mm`;
+ }, [displayPattern]);
+
return (
<Card
className={`p-0 gap-0 lg:h-full flex flex-col border-l-4 ${borderColor}`}
@@ -120,25 +140,7 @@ export function PatternCanvas() {
<CardTitle className="text-sm">Pattern Preview</CardTitle>
{hasPattern ? (
<CardDescription className="text-xs">
- {(() => {
- const displayPattern = uploadedPesData || pesData;
- return displayPattern ? (
- <>
- {(
- (displayPattern.bounds.maxX -
- displayPattern.bounds.minX) /
- 10
- ).toFixed(1)}{" "}
- ×{" "}
- {(
- (displayPattern.bounds.maxY -
- displayPattern.bounds.minY) /
- 10
- ).toFixed(1)}{" "}
- mm
- </>
- ) : null;
- })()}
+ {patternDimensions}
</CardDescription>
) : (
<CardDescription className="text-xs">
@@ -182,11 +184,11 @@ export function PatternCanvas() {
>
{/* Background layer: grid, origin, hoop */}
<Layer>
- {hasPattern && (
+ {displayPattern && (
<>
<Grid
gridSize={100}
- bounds={(uploadedPesData || pesData)!.bounds}
+ bounds={displayPattern.bounds}
machineInfo={machineInfo}
/>
<Origin />
@@ -241,42 +243,36 @@ export function PatternCanvas() {
)}
{/* Pattern info overlays */}
- {hasPattern &&
- (() => {
- const displayPattern = uploadedPesData || pesData;
- return (
- displayPattern && (
- <>
- <ThreadLegend colors={displayPattern.uniqueColors} />
+ {displayPattern && (
+ <>
+ <ThreadLegend colors={displayPattern.uniqueColors} />
- <PatternPositionIndicator
- offset={
- isUploading || patternUploaded || uploadedPesData
- ? initialUploadedPatternOffset
- : localPatternOffset
- }
- rotation={localPatternRotation}
- isLocked={patternUploaded || !!uploadedPesData}
- isUploading={isUploading}
- />
+ <PatternPositionIndicator
+ offset={
+ isUploading || patternUploaded || uploadedPesData
+ ? initialUploadedPatternOffset
+ : localPatternOffset
+ }
+ rotation={localPatternRotation}
+ isLocked={patternUploaded || !!uploadedPesData}
+ isUploading={isUploading}
+ />
- <ZoomControls
- scale={stageScale}
- onZoomIn={handleZoomIn}
- onZoomOut={handleZoomOut}
- onZoomReset={handleZoomReset}
- onCenterPattern={handleCenterPattern}
- canCenterPattern={
- !!pesData &&
- !patternUploaded &&
- !isUploading &&
- !uploadedPesData
- }
- />
- </>
- )
- );
- })()}
+ <ZoomControls
+ scale={stageScale}
+ onZoomIn={handleZoomIn}
+ onZoomOut={handleZoomOut}
+ onZoomReset={handleZoomReset}
+ onCenterPattern={handleCenterPattern}
+ canCenterPattern={
+ !!pesData &&
+ !patternUploaded &&
+ !isUploading &&
+ !uploadedPesData
+ }
+ />
+ </>
+ )}
</div>
</CardContent>
</Card>

Served by rngit 1.3.3 - Generated in 0.03s